package com.ty.common.log.utils;

import org.springframework.util.CollectionUtils;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * YAML工具类，用于读取和解析日志脱敏配置文件
 * @Author: TangYuan
 * @Date: 2025/8/19 15:55
 */
public class YmlUtils {

    /**
     * 默认脱敏配置文件名 - 默认在resources目录下
     */
    public static final String PROPERTY_NAME = "logback-desensitize.yml";

    /**
     * Key：pattern - 单条脱敏规则
     */
    public static final String PATTERN = "pattern";

    /**
     * Key：patterns - 多条脱敏规则
     */
    public static final String PATTERNS = "patterns";

    /**
     * Key:open - 是否开启脱敏功能
     */
    public static final String OPEN_FLAG = "open";

    /**
     * Key:ignore - 是否忽略大小写匹配
     */
    public static final String IGNORE = "ignore";

    /**
     * Key:脱敏配置文件根节点Key
     */
    public static final String YML_HEAD_KEY = "log-desensitize";

    /**
     * key:patterns对应key下的自定义规则Key
     */
    public static final String CUSTOM = "custom";

    public static final DumperOptions OPTIONS = new DumperOptions();

    /**
     * Yml脱敏配置文件内容 - Map格式
     */
    protected static final Map<String, Object> patternMap;

    static {
        OPTIONS.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
        patternMap = getYmlByName();
    }

    private YmlUtils() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * 根据文件名获取YML配置文件的内容
     * @return 配置信息（Map格式）
     */
    @SuppressWarnings("unchecked")
    private static Map<String, Object> getYmlByName() {
        Object fromYml;
        try {
            // 获取Yml配置文件的Map对象
            fromYml = getFromYml(YmlUtils.PROPERTY_NAME, YML_HEAD_KEY);
            // LinkedHashMap，如果不是Map类型（比如配置文件里只有log-desensitize=123456），直接返回patternMap本身
            if (fromYml instanceof Map) {
                return (Map<String, Object>) fromYml;
            }
        } catch (Exception e) {
            return new HashMap<>();
        }
        return new HashMap<>();
    }

    /**
     * 通过key从yml配置文件获取value
     * @param fileName Yml文件名
     * @param key      要获取值的key
     * @return key对应的value或者空map
     */
    @SuppressWarnings("unchecked")
    public static Object getFromYml(String fileName, String key) {
        // 创建一个Yaml对象
        Yaml yaml = new Yaml(OPTIONS);
        // 获得流
        InputStream inputStream = YmlUtils.class.getClassLoader().getResourceAsStream(fileName);
        try (inputStream) {
            if (inputStream == null) {
                return new HashMap<>();
            }
            HashMap<String, Object> map = (HashMap<String, Object>) yaml.loadAs(inputStream, HashMap.class);
            // 如果map内有值，直接返回key对应的Value，否则返回map本身
            return Objects.nonNull(map) && !map.isEmpty() ? map.get(key) : map;
        } catch (Exception e) {
            // 忽略关闭异常
        }
        return new HashMap<>();
    }

    /**
     * 获取key为pattern的单条脱敏规则
     * @return pattern对应的map，或者null（如pattern=123这种情况）
     */
    @SuppressWarnings("unchecked")
    public static Map<String, Object> getPattern() {
        Object pattern = patternMap.get(PATTERN);
        if (pattern instanceof Map) {
            return (Map<String, Object>) pattern;
        } else {
            return null;
        }
    }

    /**
     * 获取所有脱敏规则，包括pattern和patterns下的规则
     * @return 所有脱敏规则
     */
    public static Map<String, Object> getAllPattern() {
        Map<String, Object> allPattern = new HashMap<>();
        Map<String, Object> pattern = getPattern();
        Map<String, Object> patterns = getPatterns();
        if (!CollectionUtils.isEmpty(patterns)) {
            allPattern.putAll(patterns);
        }
        // 注意：patterns中的key与pattern的key重复，patterns中的不生效（Map无重复Key）
        if (!CollectionUtils.isEmpty(pattern)) {
            allPattern.putAll(pattern);
        }
        return allPattern;
    }

    /**
     * 获取key为patterns的多条脱敏规则
     * @return patterns对应的map，或者null（如patterns=123这种情况）
     */
    @SuppressWarnings("unchecked")
    public static Map<String, Object> getPatterns() {
        Map<String, Object> map = new HashMap<>();
        Object patterns = patternMap.get(PATTERNS);
        // patterns下有多个key的时候(List)
        if (patterns instanceof List) {
            // 获取key为patterns的值(List<Map<String, Object>>)
            List<Map<String, Object>> list = (List<Map<String, Object>>) patterns;
            if (!CollectionUtils.isEmpty(list)) {
                for (Map<String, Object> maps : list) {
                    assembleMap(map, maps);
                }
                return map;
            }
        }
        // patterns只有一个key的时候，且非List
        if (patterns instanceof Map) {
            assembleMap(map, (Map<String, Object>) patterns);
            return map;
        } else {
            return null;
        }
    }

    /**
     * 将patterns中每个key对应的规则按<key,规则>的方式放入map
     * @param map      存放解析结果的map
     * @param patterns patterns配置
     */
    private static void assembleMap(Map<String, Object> map, Map<String, Object> patterns) {
        // 获取patterns里key值为"key"的值(脱敏关键字)
        Object key = patterns.get("key");
        if (key instanceof String) {
            // 清除空格并以逗号分隔出一个key数组
            String[] keyArr = ((String) key).replace(" ", "").split(",");
            for (String keyStr : keyArr) {
                map.put(keyStr, patterns.get(CUSTOM));
            }
        }
    }

    /**
     * 是否开启脱敏，默认不开启
     * @return 是否开启脱敏
     */
    public static Boolean getOpen() {
        Object flag = patternMap.get(OPEN_FLAG);
        return flag instanceof Boolean ? (Boolean) flag : false;
    }

    /**
     * 是否忽略大小写匹配，默认开启
     * @return 是否忽略大小写匹配
     */
    public static Boolean getIgnore() {
        Object flag = patternMap.get(IGNORE);
        return flag instanceof Boolean ? (Boolean) flag : true;
    }
}